﻿using LJ.Abstractions.DependencyInjection;
using LJ.StreamSystem.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LJ.StreamSystem.LazyHare.Internal;

public class AggregateStreamSystemHandlerInvoker(IDependencyInjectionFactory dependencyInjectionFactory, IStreamSystemManager streamSystemManager) : IAggregateStreamSystemHandlerInvoker
{
    private readonly IDependencyInjectionFactory _dependencyInjectionFactory = dependencyInjectionFactory;
    private readonly IStreamSystemManager _streamSystemManager = streamSystemManager;


    public async Task<object> KeyInvokeAsync(AggregateStreamSystemMessage message)
    {
        var aggregateStreamSystemHandlerDescriptor = _streamSystemManager.GetAggregateStreamSystemHandlerDescriptor(message.GetApplicationId());

        using var serviceScope = _dependencyInjectionFactory.CreateScope();
        var serviceProvider = serviceScope.ServiceProvider;

        var eventHandlerInstance =
           serviceProvider.GetRequiredService(aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType);

        var method = aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType.GetMethod("SelectKeyAsync",
                [aggregateStreamSystemHandlerDescriptor.AggregateSummaryEventDataType, typeof(IDictionary<string, string>)]);

        var task = (Task<object>?)method!.Invoke(eventHandlerInstance, [message.Value, message.Headers]);
        return await task!;
    }


    public async Task<object> InitInvokeAsync(AggregateStreamSystemMessage message)
    {
        var aggregateStreamSystemHandlerDescriptor = _streamSystemManager.GetAggregateStreamSystemHandlerDescriptor(message.GetApplicationId());

        using var serviceScope = _dependencyInjectionFactory.CreateScope();
        var serviceProvider = serviceScope.ServiceProvider;

        var eventHandlerInstance =
           serviceProvider.GetRequiredService(aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType);

        var method = aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType.GetMethod("InitAsync",
                [typeof(IDictionary<string, string>)]);

        var task = (Task<object>?)method!.Invoke(eventHandlerInstance, [message.Headers]);
        return await task!;
    }

    public async Task<object> SummaryInvokeAsync(AggregateStreamSystemMessage message)
    {
        var aggregateStreamSystemHandlerDescriptor = _streamSystemManager.GetAggregateStreamSystemHandlerDescriptor(message.GetApplicationId());

        using var serviceScope = _dependencyInjectionFactory.CreateScope();
        var serviceProvider = serviceScope.ServiceProvider;

        var eventHandlerInstance =
           serviceProvider.GetRequiredService(aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType);

        var method = aggregateStreamSystemHandlerDescriptor.AggregateStreamSystemHandlerType.GetMethod("SelectKeyAsync",
               [aggregateStreamSystemHandlerDescriptor.AggregateEventDataType, aggregateStreamSystemHandlerDescriptor.AggregateSummaryEventDataType, typeof(IDictionary<string, string>)]);

        var task = (Task<object>?)method!.Invoke(eventHandlerInstance, [message.Value, message.SummaryValue, message.Headers]);
        return await task!;
    }
}
